package com.thinkit.log.service.impl;
import cn.hutool.json.JSONUtil;
import com.thinkit.core.base.BaseServiceImpl;
import com.thinkit.log.annotation.Logs;
import com.thinkit.log.mapper.LogMapper;
import com.thinkit.log.model.Log;
import com.thinkit.log.model.LogDto;
import com.thinkit.log.service.LogService;
import com.thinkit.utils.utils.Checker;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.UnknownHostException;
/**
 * <p>
 * 系统日志 服务实现类
 * </p>
 * @author lgs
 * @since 2019-08-12
 */
@Transactional
@Service
public class LogServiceImpl extends BaseServiceImpl<LogDto, Log, LogMapper> implements LogService {

    @Override
    public void saveLog(ProceedingJoinPoint joinPoint, int time) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        LogDto sysLog = new LogDto();
        Logs logs = method.getAnnotation(Logs.class);
        if (logs != null) {
            String opera=logs.operaEnum().getCode()+logs.operation();
            sysLog.setOperation(opera);
            sysLog.setModule(logs.module().getName());
            sysLog.setType(logs.module().getCode());
        }
        // 请求的方法名
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = signature.getName();
        sysLog.setMethod(className + "." + methodName + "()");
        // 请求的参数
        Object[] args = joinPoint.getArgs();
        try {
            if(Checker.BeNotEmpty(args)){
                String params="";
                for(Object o:args){
                    if(Checker.BeNotNull(o) && Checker.BeNotBlank(o.toString())){
                        params += JSONUtil.toJsonStr(o)+"|";
                    }
                }
                if(Checker.BeNotBlank(params)&&params.endsWith("|"))
                    params=params.substring(0,params.length()-1);
                sysLog.setParams(params);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 获取request
        HttpServletRequest request=((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        // 设置IP地址
        sysLog.setIp(getIpAddr(request));
        // 用户名
        String userId = getUserId();
        String userAccount = getAccount();
        if (Checker.BeNotBlank(userId)) {
            sysLog.setUserId(userId);
        }
        if (Checker.BeNotBlank(userAccount)) {
            sysLog.setUserAccount(userAccount);
        }
        sysLog.setTime(time).setId(id());
        String params = sysLog.getParams();
        if(Checker.BeNotBlank(params)){
            params =  emojiConverter.toHtml(params);
            sysLog.setParams(params);
        }
        insert(sysLog);
    }

    /**
     * 获取访问者IP
     *
     * 在一般情况下使用Request.getRemoteAddr()即可，但是经过nginx等反向代理软件后，这个方法会失效。
     *
     * 本方法先从Header中获取X-Real-IP，如果不存在再从X-Forwarded-For获得第一个IP(用,分割)，
     * 如果还不存在则调用Request .getRemoteAddr()。
     *
     * @param request
     * @return
     */
    public static String getIpAddr(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("X-Real-IP");
        }
        if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        if (StringUtils.isNotBlank(ip) && !"unknown".equalsIgnoreCase(ip)
                && StringUtils.contains(ip, ",")) {
            // 多次反向代理后会有多个IP值，第一个为真实IP。
            ip = StringUtils.substringBefore(ip, ",");
        }
        // 处理localhost访问
        if (StringUtils.isBlank(ip) || "unkown".equalsIgnoreCase(ip)
                || StringUtils.split(ip, ".").length != 4) {
            try {
                InetAddress inetAddress = InetAddress.getLocalHost();
                ip = inetAddress.getHostAddress();
            } catch (UnknownHostException e) {
                e.printStackTrace();
            }
        }
        return ip;
    }
}
